package icasue.reflect.handles.exception;

import icasue.reflect.handles.HandleSupplier;
import icasue.reflect.handles.OFAble;
import icasue.reflect.handles.object.ObjectOF;
import icasue.reflect.exceptions.HandleException;
import icasue.reflect.handles.classes.ClassOF;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.function.Function;

/**
 * @Author: Qiao Hang
 * @CreateDate: 2020/12/1 下午1:42
 * @UpdateDate:
 * @Description:
 */
public class ExceptionOF implements OFAble {

    /**
     * runtimeExc_  (null/string)  doc: to construct an instance of RuntimeException.
     * handleExc_  (null/string)  doc: to construct an instance of HandleException.
     *
     * All method check pass.
     */

    public static Function<String,RuntimeException> runtimeExc_ = (mes) -> {
        Constructor runtimeConstruct = null;
        if (ObjectOF.isNull_.test(mes)) {
            return (RuntimeException) ClassOF.newInstance_.apply(RuntimeException.class);
        } else {
            runtimeConstruct = ClassOF.getDeclaredConstructor_.apply(new Object[]{RuntimeException.class, new Class[]{String.class}});
            try {
                return (RuntimeException)runtimeConstruct.newInstance(mes);
            } catch (Throwable throwable) {
                throw new RuntimeException("ExceptionOF.handleExc_ : Construct RuntimeException with param message occur an error : " + throwable.getMessage());
            }
        }
    };

    public static Function<String, HandleException> handleExc_ = (mes) -> {
        Constructor handleExceptionConstruct = null;
        if (ObjectOF.isNull_.test(mes)) {
            return (HandleException) ClassOF.newInstance_.apply(HandleException.class);
        } else {
            handleExceptionConstruct = ClassOF.getDeclaredConstructor_.apply(new Object[]{HandleException.class, new Class[]{String.class}});
            try {
                return (HandleException) handleExceptionConstruct.newInstance(mes);
            } catch (Throwable throwable) {
                throw new RuntimeException("ExceptionOF.handleExc_ : Construct HandleException with param message occur an error : " + throwable.getMessage());
            }
        }
    };

    public static HandleSupplier.FunctionAry<HandleException> handleExcInvocation_ = (mesAndError) -> {
        Constructor handleExceptionConstruct = null;
        if (ObjectOF.isNull_.test(mesAndError) || mesAndError.length == 0) {
            return (HandleException) ClassOF.newInstance_.apply(HandleException.class);
        } else {
            handleExceptionConstruct = ClassOF.getDeclaredConstructor_.apply(new Object[]{HandleException.class, new Class[]{String.class}});
            try {
                String mes = null;
                if(mesAndError.length == 1){
                    if(mesAndError[0] instanceof String)
                        mes = mesAndError[0].toString();
                    else if(mesAndError[0] instanceof Throwable){
                        if(mesAndError[0] instanceof InvocationTargetException){
                            mes = InvocationTargetException.class.cast(mesAndError[0]).getTargetException().getMessage();
                        }else {
                            mes = Throwable.class.cast(mesAndError[0]).getMessage();
                        }
                    }else {
                        mes = String.valueOf(mesAndError[0]);
                    }
                }else {
                    mes = String.valueOf(mesAndError[0]);
                    if(mesAndError[1] instanceof String)
                        mes = mes.concat(String.valueOf(mesAndError[1]));
                    else if(mesAndError[1] instanceof Throwable){
                        if(mesAndError[1] instanceof InvocationTargetException){
                            mes = mes.concat(InvocationTargetException.class.cast(mesAndError[1]).getTargetException().getMessage());
                        }else {
                            mes = mes.concat(Throwable.class.cast(mesAndError[1]).getMessage());
                        }
                    }else {
                        mes = mes.concat(String.valueOf(mesAndError[1]));
                    }
                }
                return (HandleException) handleExceptionConstruct.newInstance(mes);
            } catch (Throwable throwable) {
                throw new RuntimeException("ExceptionOF.handleExc_ : Construct HandleException with param message occur an error : " + throwable.getMessage());
            }
        }
    };

}
